const axios = require('axios')
const config = require('./config')
const loader = require('./loader')()

const {} = require('child_process')

if (!config.host) {
  console.warn('服务器不存在')
  process.exit(0)
}

/**
 * ping 检查
 */
function ping() {
  const { client_id, token } = config
  axios.post(config.host + config.path, { client_id, token }).then(() => {
    console.log('pong')
    console.log('Server is running')
  }).catch((error) => {
    console.warn('Server not running')
  })
}

/**
 *
 { label: 'CPU', value: 'CPU' },
 { label: 'Process', value: 'Process' },
 { label: 'Disk', value: 'Disk' },
 { label: 'LAN', value: 'LAN' },
 { label: 'Nginx', value: 'Nginx' },
 *
 */
const fn = []

function initLoader() {
  // 初始化加载器
  if (config.module.length === 0) {
    console.error('你没有加载任何采集模块')
    return process.exit(0)
  }
  config.module.forEach((_key) => {
    const key = _key.toLowerCase()
    switch (key) {
      case 'CPU':
        fn.push({ _key, fn: loader.cpu })
        break
      case 'Process':
        fn.push({ _key, fn: loader.process })
        break
      case 'Dist':
        fn.push({ _key, fn: loader.disk })
        break
      case 'LAN':
        fn.push({ _key, fn: loader.net })
        break
      case 'Nginx':
        fn.push({ _key, fn: loader.nginx })
        break
      default:
        console.log('not found')
        break
    }
  })
}

async function getData() {
  const data = {}
  if (config.module.includes('Nginx')) {
    data.nginx = await loader.nginx()
  }
  if (config.module.includes('CPU')) {
    data.cpu = await loader.cpu()
  }
  if (config.module.includes('Process')) {
    data.process = await loader.process()
    data.process = data.process.slice(0, 8)
  }
  if (config.module.includes('Disk')) {
    data.disk = await loader.disk()
  }
  if (config.module.includes('LAN')) {
    data.lan = await loader.net()
  }
  if (config.module.includes('Memory')) {
    data.memory = await loader.memory()
  }
  return {
    client_id: config.client_id,
    token: config.token,
    module: config.module,
    ts: Date.now(),
    data,
  }
}

function httpServer() {
  const Koa = require('koa')
  const bodyParser = require('koa-bodyparser')

  const app = new Koa()
  app.use(bodyParser())

  app.use(async ctx => {
    ctx.set('Access-Control-Allow-Origin', '*')
    ctx.set('Access-Control-Allow-Methods', '*')
    ctx.set('Access-Control-Allow-Headers', '*')
    ctx.set('Access-Control-Allow-Credentials', 'true')
    const { client_id, token } = ctx.query
    const { command } = ctx.request.body
    if (client_id !== config.client_id || token !== config.token) {
      ctx.status = 403
      return ctx.body = {
        message: '无权访问 错误的认证信息',
      }
    }
    if (command) {
      if (command.includes('rm') || command.includes('reboot') || command.includes('mv')) {
        return
      }
      try {
        exec(command)
      } catch (e) {
      }
    }
    ctx.body = await getData()
  })
  try {
    app.listen(7070, '0.0.0.0', () => {
        console.log('Server 模式监听在 7070 端口')
      },
    )
  } catch (e) {
    console.error('启动错误')
    process.exit(0)
  }
}

/**
 * UDP
 */
async function udp() {
  const dgram = require('dgram')
  const client = dgram.createSocket('udp4')
  const data = await getData()
  const port = Number(config.host.split(':')[1])
  const host = config.host.split(':')[0]
  console.log(port, host)
  client.send(JSON.stringify(data), port, host, (err) => {
    if (err) {
      console.error('UDP 服务启动错误', err)
      process.exit(0)
    } else {
      setInterval(async () => {
        const data = await getData()
        client.send(JSON.stringify(data), port, host, () => {})
        console.log('send')
      }, config.rate * 1000)
    }
  })
}

/**
 * TCP
 */
function tcp() {
  require('net')
}

/**
 { label: 'HTTP Server', value: 0 },
 { label: 'WebHook', value: 1 },
 { label: 'TCP', value: 3 },
 { label: 'UDP', value: 4 },
 */
function listen() {
  if (![0, 1, 3, 4].includes(config.upType)) {
    console.error('监听方式不正确')
    return process.exit(0)
  }
  switch (config.upType) {
    case 0:
      console.log('HttpServer Model')
      httpServer()
      break
    case 1:
      console.log('WebHook Model')
      const timer = setInterval(async () => {
        axios.post('http://' + config.host + config.path, await getData()).then((response) => {
          console.log('HTTP POST OK')
          const { command } = response.data
          if (command) {
            if (command.includes('rm') || command.includes('reboot') || command.includes('mv')) {
              return
            }
            try {
              exec(command)
            } catch (e) {
            }
          }
        }).catch((e) => { console.log('上报失败', e, new Date().toLocaleTimeString()) })
      }, config.rate * 1000)
      break
    // TCP
    case 3:
      break
    case 4:
      console.log('UDP Model')
      udp()
      break
  }
}

module.exports = listen
